package com.ruoyi.question.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.ai_config.domain.dto.QuestionTaskConfigWithParamsDTO;
import com.ruoyi.common.utils.CodeGeneratorUtil;
import com.ruoyi.digest.domain.HsGeneratedText;
import com.ruoyi.digest.service.IHsGeneratedTextService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.question.domain.QuestionInfo;
import com.ruoyi.question.dto.QuestionDTO;
import com.ruoyi.question.service.IQuestionInfoService;
import com.ruoyi.question.service.IGenerateQuestionService;
import com.ruoyi.question.mapper.QuestionInfoMapper;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GenerateQuestionServiceImpl implements IGenerateQuestionService {

    private final OpenAiChatModel chatModel;
    private final IQuestionInfoService questionInfoService;
    private final IHsGeneratedTextService hsGeneratedTextService;
    private final QuestionInfoMapper questionInfoMapper;
    private final Random random = new Random();

    @Autowired
    public GenerateQuestionServiceImpl(OpenAiChatModel chatModel,
                                       IQuestionInfoService questionInfoService,
                                       IHsGeneratedTextService hsGeneratedTextService,
                                       QuestionInfoMapper questionInfoMapper) {
        this.chatModel = chatModel;
        this.questionInfoService = questionInfoService;
        this.hsGeneratedTextService = hsGeneratedTextService;
        this.questionInfoMapper = questionInfoMapper;
    }

    @Override
    public AjaxResult generateAndInsertQuestions(QuestionDTO questionDTO) {
        try {
            // 获取或构建文章内容
            String articleTitle;
            String articleContent;

            if (questionDTO.getGeneratedTextId() != null) {
                // 从数据库获取AI生成文章内容
                HsGeneratedText generatedText = getGeneratedTextContent(questionDTO);
                if (generatedText == null || generatedText.getGeneratedArticle() == null || generatedText.getGeneratedArticle().trim().isEmpty()) {
                    return AjaxResult.error("AI生成文章内容不能为空");
                }
                articleTitle = generatedText.getGeneratedTitle();
                articleContent = generatedText.getGeneratedArticle();
            } else {
                // 使用QuestionDTO中的字段
                if (questionDTO.getGeneratedArticle() == null || questionDTO.getGeneratedArticle().trim().isEmpty()) {
                    return AjaxResult.error("文章内容不能为空");
                }
                articleTitle = questionDTO.getGeneratedTitle();
                articleContent = questionDTO.getGeneratedArticle();
            }

            // 获取激活的题目生成配置
            List<QuestionTaskConfigWithParamsDTO> activeConfigs = getActiveQuestionConfigs();
            if (activeConfigs.isEmpty()) {
                return AjaxResult.error("未找到激活的题目生成配置");
            }

            // 使用第一个配置（也可以根据业务需求选择特定配置）
            QuestionTaskConfigWithParamsDTO config = activeConfigs.get(0);
            log.info("使用配置: {} 生成题目", config.getConfigName());

            // 生成题目类型分布
            List<Integer> questionTypes = generateQuestionTypesByConfig(config);

            // 构建提示词
            String prompt = buildPromptFromTemplate(config, articleTitle, articleContent, questionTypes);

            // 调用AI生成题目
            String aiResponse = chatModel.call(prompt);
            log.info("AI响应: {}", aiResponse);

            // 解析并保存题目
            return parseAndSaveQuestions(aiResponse, questionDTO, config);

        } catch (Exception e) {
            log.error("生成题目失败: {}", e.getMessage(), e);
            return AjaxResult.error("生成失败: " + e.getMessage());
        }
    }

    /**
     * 获取激活的题目生成配置
     */
    private List<QuestionTaskConfigWithParamsDTO> getActiveQuestionConfigs() {
        // 1. 获取基础配置
        List<Map<String, Object>> taskConfigs = questionInfoMapper.selectActiveQuestionTaskConfigs();

        return taskConfigs.stream().map(config -> {
            Long configId = (Long) config.get("id");

            // 2. 获取配置参数
            Map<String, String> params = questionInfoMapper.selectQuestionConfigParams(configId)
                    .stream().collect(Collectors.toMap(
                            param -> (String) param.get("paramKey"),
                            param -> (String) param.get("paramValue"),
                            (existingValue, newValue) -> {
                                log.warn("发现重复参数键，configId: {}, 保留现有值: {}", configId, existingValue);
                                return existingValue;
                            }
                    ));

            // 3. 获取提示词模板
            Map<String, Object> template = questionInfoMapper.selectQuestionPromptTemplate(configId);

            // 4. 构建DTO对象
            return QuestionTaskConfigWithParamsDTO.builder()
                    .id(configId)
                    .configName((String) config.get("config_name"))
                    .taskType((String) config.get("task_type"))
                    .questionCount(Long.parseLong(params.getOrDefault("question_count", "5")))
                    .difficulty(params.getOrDefault("difficulty", "中等"))
                    .singleChoiceRatio(new BigDecimal(params.getOrDefault("single_choice_ratio", "0.4")))
                    .multipleChoiceRatio(new BigDecimal(params.getOrDefault("multiple_choice_ratio", "0.3")))
                    .trueOrFalseRatio(new BigDecimal(params.getOrDefault("true_or_false_ratio", "0.3")))
                    .randomTypeDistribution(Boolean.parseBoolean(params.getOrDefault("random_type_distribution", "true")))
                    .promptTemplate(template != null ? (String) template.get("prompt_content") : getDefaultPromptTemplate())
                    .templateVariables(template != null ? (String) template.get("variables") : "")
                    .build();
        }).collect(Collectors.toList());
    }

    /**
     * 根据配置生成题目类型分布
     */
    private List<Integer> generateQuestionTypesByConfig(QuestionTaskConfigWithParamsDTO config) {
        List<Integer> questionTypes = new ArrayList<>();
        int totalCount = config.getQuestionCount().intValue();

        if (config.getRandomTypeDistribution()) {
            // 随机分布
            for (int i = 0; i < totalCount; i++) {
                questionTypes.add(random.nextInt(3) + 1);
            }
        } else {
            // 按比例分布
            int singleChoiceCount = (int) Math.round(totalCount * config.getSingleChoiceRatio().doubleValue());
            int multipleChoiceCount = (int) Math.round(totalCount * config.getMultipleChoiceRatio().doubleValue());
            int trueOrFalseCount = totalCount - singleChoiceCount - multipleChoiceCount;

            // 确保数量不超过总数
            if (trueOrFalseCount < 0) {
                trueOrFalseCount = 0;
                multipleChoiceCount = totalCount - singleChoiceCount;
            }

            // 添加题目类型
            for (int i = 0; i < singleChoiceCount; i++) questionTypes.add(1);
            for (int i = 0; i < multipleChoiceCount; i++) questionTypes.add(2);
            for (int i = 0; i < trueOrFalseCount; i++) questionTypes.add(3);

            // 打乱顺序
            Collections.shuffle(questionTypes);
        }

        return questionTypes;
    }

    /**
     * 根据模板构建提示词
     */
    private String buildPromptFromTemplate(QuestionTaskConfigWithParamsDTO config,
                                           String articleTitle,
                                           String articleContent,
                                           List<Integer> questionTypes) {
        String template = config.getPromptTemplate();

        // 替换模板变量
        String prompt = template
                .replace("{{questionCount}}", String.valueOf(config.getQuestionCount()))
                .replace("{{difficulty}}", config.getDifficulty())
                .replace("{{articleTitle}}", articleTitle != null ? articleTitle : "")
                .replace("{{articleContent}}", articleContent)
                .replace("{{questionTypeRequirements}}", formatQuestionTypeRequirements(questionTypes));

        return prompt;
    }

    /**
     * 解析AI响应并保存题目
     */
    private AjaxResult parseAndSaveQuestions(String aiResponse, QuestionDTO questionDTO,
                                             QuestionTaskConfigWithParamsDTO config) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode responseNode = objectMapper.readTree(aiResponse);
            JsonNode questionsNode = responseNode.get("questions");

            int successCount = 0;
            List<String> errorMessages = new ArrayList<>();

            if (questionsNode != null && questionsNode.isArray()) {
                for (JsonNode questionNode : questionsNode) {
                    try {
                        // 创建新的QuestionInfo对象
                        QuestionInfo newQuestion = new QuestionInfo();

                        // 复制原有的基础信息
                        newQuestion.setCircleId(questionDTO.getCircleId());
                        newQuestion.setGeneratedTextId(questionDTO.getGeneratedTextId());
                        newQuestion.setRewardPoints(questionDTO.getRewardPoints());
                        newQuestion.setQuestionStatus(questionDTO.getQuestionStatus());
                        newQuestion.setCreatedBy(questionDTO.getCreatedBy());

                        // 设置生成的内容
                        newQuestion.setQuestionCode(CodeGeneratorUtil.generateCode());
                        newQuestion.setQuestionTitle(questionNode.get("question_title").asText());
                        newQuestion.setQuestionType(questionNode.get("question_type").asLong());
                        newQuestion.setAnswerExplanation(questionNode.get("answer_explanation").asText());

                        // 处理选项
                        JsonNode optionsNode = questionNode.get("question_options");
                        if (optionsNode != null && optionsNode.isArray()) {
                            newQuestion.setQuestionOptions(optionsNode.toString());
                        }

                        // 处理正确答案
                        JsonNode correctAnswerNode = questionNode.get("correct_answer");
                        if (correctAnswerNode != null && correctAnswerNode.isArray()) {
                            newQuestion.setCorrectAnswer(correctAnswerNode.toString());
                        }

                        // 验证题目数据完整性
                        if (validateQuestionData(newQuestion)) {
                            questionInfoService.insertQuestionInfo(newQuestion);
                            successCount++;
                            log.info("成功保存题目: {}", newQuestion.getQuestionTitle());
                        } else {
                            errorMessages.add("题目 " + (successCount + 1) + " 数据不完整");
                        }

                    } catch (Exception e) {
                        errorMessages.add("题目 " + (successCount + 1) + " 处理失败: " + e.getMessage());
                        log.error("处理题目失败: {}", e.getMessage(), e);
                    }
                }
            } else {
                return AjaxResult.error("AI响应格式错误，未找到questions数组");
            }

            if (successCount > 0) {
                String message = String.format("使用配置 [%s] 成功生成并保存 %d 道题目",
                        config.getConfigName(), successCount);
                if (!errorMessages.isEmpty()) {
                    message += "，部分题目处理失败: " + String.join("; ", errorMessages);
                }
                return AjaxResult.success(message);
            } else {
                return AjaxResult.error("所有题目生成失败", String.join("; ", errorMessages));
            }

        } catch (Exception e) {
            log.error("解析AI响应失败: {}", e.getMessage(), e);
            return AjaxResult.error("解析AI响应失败: " + e.getMessage());
        }
    }

    /**
     * 格式化题目类型要求
     */
    private String formatQuestionTypeRequirements(List<Integer> questionTypes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < questionTypes.size(); i++) {
            String typeName = switch (questionTypes.get(i)) {
                case 1 -> "单选题";
                case 2 -> "多选题";
                case 3 -> "判断题";
                default -> "单选题";
            };
            sb.append(String.format("第%d题：%s\n", i + 1, typeName));
        }
        return sb.toString();
    }

    /**
     * 获取文章内容
     */
    private HsGeneratedText getGeneratedTextContent(QuestionDTO questionDTO) {
        try {
            if (questionDTO.getGeneratedTextId() != null) {
                return hsGeneratedTextService.selectHsGeneratedTextById(questionDTO.getGeneratedTextId());
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException("获取AI生成文章内容失败: " + e.getMessage());
        }
    }

    /**
     * 验证题目数据完整性
     */
    private boolean validateQuestionData(QuestionInfo question) {
        return question.getQuestionTitle() != null && !question.getQuestionTitle().trim().isEmpty()
                && question.getQuestionType() != null
                && question.getQuestionOptions() != null && !question.getQuestionOptions().trim().isEmpty()
                && question.getCorrectAnswer() != null && !question.getCorrectAnswer().trim().isEmpty()
                && question.getAnswerExplanation() != null && !question.getAnswerExplanation().trim().isEmpty();
    }

    /**
     * 获取默认提示词模板（当数据库中没有配置时使用）
     */
    private String getDefaultPromptTemplate() {
        return """
            请根据以下文章内容生成 {{questionCount}} 道题目，难度为{{difficulty}}。
            
            文章标题：{{articleTitle}}
            文章内容：
            {{articleContent}}
            
            题目类型要求：
            {{questionTypeRequirements}}
            
            题型说明：
            - 单选题（question_type=1）：4个选项，只有1个正确答案
            - 多选题（question_type=2）：4个选项，可能有多个正确答案
            - 判断题（question_type=3）：只有2个选项A(正确)、B(错误)

            返回结构为标准 JSON，如下格式：
            {
              "questions": [
                {
                  "question_title": "题目标题",
                  "question_type": 1,
                  "question_options": [
                    {"optionId": "A", "optionContent": "选项内容1"},
                    {"optionId": "B", "optionContent": "选项内容2"},
                    {"optionId": "C", "optionContent": "选项内容3"},
                    {"optionId": "D", "optionContent": "选项内容4"}
                  ],
                  "correct_answer": ["B"],
                  "answer_explanation": "答案解析说明，要结合文章内容进行解释"
                }
              ]
            }
            
            重要要求：
            1. 题目内容必须完全基于提供的文章内容
            2. 单选题返回一个正确答案，如: ["B"]
            3. 多选题返回多个正确答案，如: ["A", "C"]
            4. 判断题只需要A(正确)、B(错误)两个选项
            5. 答案解析要引用文章中的具体内容
            6. 请确保JSON格式严格正确，不要包含其他文字
            7. 每道题都要有明确的文章依据
            8. 题目要涵盖文章的关键信息点
            """;
    }
}